# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2022/6/26 13:24
# @Author : xyjiang1216
# @Email : jiangxuyan@nudt.edu.cn
# @File : map_tbl_structure.py
# @Version: planner_builder 1.0

import ctypes

from tsn_builder_struct.table_length import MAP_TBL_LEN

c_uint32 = ctypes.c_uint32


class MapEntry_bits(ctypes.BigEndianStructure):
    _fields_ = [
        # entry1
        ("valid", c_uint32, 1),
        ("reserved", c_uint32, 18),
        ("five_tuple_mask", c_uint32, 5),
        ("ip_protocol", c_uint32, 8),
        # entry2
        ("dport", c_uint32, 16),
        ("sport", c_uint32, 16),
        # entry3
        ("dip", c_uint32, 32),
        # entry4
        ("sip", c_uint32, 32),
        # entry5
        ("reserved1", c_uint32, 9),
        ("ipv", c_uint32, 3),
        ("flow_id", c_uint32, 14),
        ("redundant_flag", c_uint32, 1),
        ("dbufid", c_uint32, 5),
        # entry6
        ("reserved2", c_uint32, 32),
        # entry7
        ("reserved3", c_uint32, 32),
        # entry8
        ("reserved4", c_uint32, 32),
    ]


class MapEntry_bytes(ctypes.BigEndianStructure):
    _fields_ = [
        ("entry1", c_uint32, 32),
        ("entry2", c_uint32, 32),
        ("entry3", c_uint32, 32),
        ("entry4", c_uint32, 32),
        ("entry5", c_uint32, 32),
        ("entry6", c_uint32, 32),
        ("entry7", c_uint32, 32),
        ("entry8", c_uint32, 32)
    ]


class MapEntry_union(ctypes.Union):
    _fields_ = [
        ("bit", MapEntry_bits),
        ("byte", MapEntry_bytes)
    ]


class MapTblEachNode:
    def __init__(self,
                 node_id: int):
        self.node_id = node_id
        self.tbl_len = MAP_TBL_LEN
        self.tbl_each_node = []

    def append_entry(self,
                     entry: MapEntry_union):
        if len(self.tbl_each_node) <= self.tbl_len:
            self.tbl_each_node.append(entry)
        else:
            print('ERROR - map tbl exceeds %d at node %d' % (self.tbl_len, self.node_id))
            exit(0)


class MapTbl:
    def __init__(self):
        self.tbl_set = []

    def append_tbl(self,
                   tbl: MapTblEachNode):
        self.tbl_set.append(tbl)
